package me.ezitku.shttp

import android.content.ComponentCallbacks
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.net.InetAddress

//private fun Any.isAdded(): Boolean {
//    if (this is Activity) {
//        return !isDestroyed
//    } else if (this is Fragment) {
//        return this.isAdded
//    }
//    return true
//}

private fun isInternetAvailable(): Boolean {
    return try {
        val ipAddr = InetAddress.getByName("baidu.com")
        //You can replace it with your name
        !ipAddr.equals("")

    } catch (e: Exception) {
        false
    }
}

fun <T> Call<T>.result(action: Result<T>.() -> Unit): Call<T> {
    val result = Result<T>()
    action(result)
    val errRes = ErrResult()
    result._loading.invoke()
//    if (!isInternetAvailable()) {
//        errRes.requestUrl = ""
//        errRes.message = "Network is Not Available"
//        result._err.invoke(errRes)
//        result._loaded.invoke(this)
//        errRes.excepption = null
//        return this
//    }
    enqueue(object : Callback<T> {
        override fun onResponse(call: Call<T>, response: Response<T>?) {
            if ((result._context != null)) {

            } else {
                if (response?.isSuccessful!!) {
                    result._ok.invoke(response.body()!!)
                    result._loaded.invoke(call)
                    return
                } else {
                    errRes.message = try {
                        response.errorBody()!!.string()
                    } catch (e: Exception) {
                        response.message()
                    }
                    errRes.code = response.code()

                    result._err.invoke(errRes)

                    result._loaded.invoke(call)
                }
            }
        }

        override fun onFailure(call: Call<T>, t: Throwable?) {
            if (call.isCanceled) {
                result._cancel(call)
            } else if ((result._context != null)) {

            } else {
                errRes.requestUrl = call.request().url().host()
                errRes.message = "${t?.message}"
                result._err.invoke(errRes)

                result._loaded.invoke(call)
                errRes.excepption = t
            }

        }
    })
    return this
}

class Result<T> {
    internal var _ok: (data: T) -> Unit = {}
    internal var _err: (err: ErrResult) -> Unit = {}
    internal var _loading: () -> Unit = {}
    internal var _loaded: (Call<T>) -> Unit = {}
    internal var _cancel: (Call<T>) -> Unit = {}

    internal var _context: Any? = null


    private fun ComponentCallbacks.initContext() {
        _context = this
    }

    //UI中
    //SuccessFully

    fun ComponentCallbacks.ok(action: (data: T) -> Unit) {
        this.initContext()
        _ok = action
    }
//    fun Fragment.ok(action: (data: T) -> Unit) {
//        this.initContext()
//        _ok = action
//    }


    //Error
    fun ComponentCallbacks.err(action: (err: ErrResult) -> Unit) {
        this.initContext()
        _err = action
    }
//    fun Fragment.err(action: (err: ErrResult) -> Unit) {
//        this.initContext()
//        _err = action
//    }

    fun ComponentCallbacks.loading(action: () -> Unit) {
        this.initContext()
        _loading = action
    }

//    fun Fragment.loading(action: () -> Unit) {
//        this.initContext()
//        _loading = action
//    }

    fun ComponentCallbacks.loaded(action: (Call<T>) -> Unit) {
        this.initContext()
        _loaded = action
    }

//    fun Fragment.loaded(action: () -> Unit) {
//        this.initContext()
//        _loaded = action
//    }

    //UI之外
    fun success(action: (data: T) -> Unit) {
        _ok = action
    }

    fun error(action: (err: ErrResult) -> Unit) {
        _err = action
    }

    fun requesting(action: () -> Unit) {
        _loading = action
    }

    fun complete(action: (Call<T>) -> Unit) {
        _loaded = action
    }

    fun cancel(action: (Call<T>) -> Unit) {
        _cancel = action
    }


//    fun loadedOK(action: () -> Unit) {
//        _loadedOk = action
//    }
//
//    fun loadedErr(action: () -> Unit) {
//        _loadedErr = action
//    }


}


class ErrResult {
    var code: Int = -1
    var message: String = ""
    var excepption: Throwable? = null
    var requestUrl = ""
}